<?php

class Captcha {

    protected static $_instance = null;
    public $option = array('length' => 4, 'font' => BASE_PATH . "/tmp/font/font.ttf", 'size' => 30, 'width' => 140, 'height' => 50);

    function __construct() {
        if (Yaf_Registry::get("config")->captcha) {
            $this->option = array_merge($this->option, Yaf_Registry::get("config")->captcha->toArray());
        }
    }

    /**
     * 单例方法
     * @return Captcha
     */
    public static function getInstance() {
        if (null === self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    /**
     * 生成随机字符
     * @return bool 成功时返回生成的字符
     */
    function text() {
        $string = '';
        $key = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9');
        $keynum = count($key) - 1;
        for ($i = 0; $i < $this->option['length']; $i++) {
            $string .= (string) $key[mt_rand(0, $keynum)];
        }
        return ($string == '' || strlen($string) < $this->option['length']) ? 'ABCD' : $string;
    }

    /**
     * 生成验证码
     */
    function get() {
        $text = $this->text();
        //header('Content-type: image/png');

        $im = imagecreatetruecolor($this->option['width'], $this->option['height']);
        //文字颜色
        $text_color = ImageColorAllocate($im, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
        //背景颜色
        $bg_color = ImageColorAllocate($im, mt_rand(100, 255), mt_rand(100, 255), mt_rand(100, 255));
        imagefill($im, 0, 0, $bg_color);

        //画文字
        for ($i = 0; $i < strlen($text); $i++) {
            $tmp = substr($text, $i, 1);
            $array = array(-1, 1);
            $p = array_rand($array);
            $an = $array[$p] * mt_rand(1, 10); //角度
            imagettftext($im, $this->option['size'], $an, 0 + $i * $this->option['size'], 40, $text_color, $this->option['font'], $tmp);
        }

        //正弦扭曲文字
        $distortion_im = imagecreatetruecolor($this->option['width'], $this->option['height']);
        imagefill($distortion_im, 0, 0, $bg_color);
        for ($i = 0; $i < $this->option['width']; $i++) {
            for ($j = 0; $j < $this->option['height']; $j++) {
                $rgb = imagecolorat($im, $i, $j);
                if ((int) ($i + 5 + sin($j / $this->option['height'] * 2 * M_PI) * 10) <= imagesx($distortion_im) && (int) ($i + 5 + sin($j / $this->option['height'] * 2 * M_PI) * 10) >= 0) {
                    imagesetpixel($distortion_im, (int) ($i + 5 + sin($j / $this->option['height'] * 2 * M_PI - M_PI * 0.1) * 4), $j, $rgb);
                }
            }
        }

        //画干扰像素点
        $count = 300; //干扰像素的数量
        for ($i = 0; $i < $count; $i++) {
            $randcolor = ImageColorallocate($distortion_im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
            imagesetpixel($distortion_im, mt_rand() % $this->option['width'], mt_rand() % $this->option['height'], $randcolor);
        }

        // 画干扰线
        for ($i = 0; $i < 5; $i++) {
            $font_color = imagecolorallocate($distortion_im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
            imagearc($distortion_im, mt_rand(- $this->option['width'], $this->option['width']), mt_rand(- $this->option['height'], $this->option['height']), mt_rand(30, $this->option['width'] * 2), mt_rand(20, $this->option['height'] * 2), mt_rand(0, 360), mt_rand(0, 360), $font_color);
        }

        //加入干扰线
        $rand = mt_rand(5, 30);
        $rand1 = mt_rand(15, 25);
        $rand2 = mt_rand(5, 10);
        for ($yy = $rand; $yy <= +$rand + 2; $yy++) {
            for ($px = -80; $px <= 80; $px = $px + 0.1) {
                $x = $px / $rand1;
                if ($x != 0) {
                    $y = sin($x);
                }
                $py = $y * $rand2;
                imagesetpixel($distortion_im, $px + 80, $py + $yy, $text_color);
            }
        }
        if (!isset($_SESSION))
            session_start();

        //设置文件头;
        header("Content-Type: image/png");
        imagepng($distortion_im);

        //销毁一图像,释放与image关联的内存;
        imagedestroy($distortion_im);
        imagedestroy($im);
        $_SESSION['captcha'] = $text;
        exit;
    }

}
